/*
 * Unidata Platform Community Edition
 * Copyright (c) 2013-2020, UNIDATA LLC, All rights reserved.
 * This file is part of the Unidata Platform Community Edition software.
 *
 * Unidata Platform Community Edition is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Unidata Platform Community Edition is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */
package org.unidata.mdm.dq.core.service.impl.instance;

import java.time.OffsetDateTime;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.unidata.mdm.core.type.model.instance.AbstractNamedDisplayableCustomPropertiesImpl;
import org.unidata.mdm.dq.core.type.model.instance.CleanseFunctionElement;
import org.unidata.mdm.dq.core.type.model.instance.EnrichingRuleElement;
import org.unidata.mdm.dq.core.type.model.instance.QualityRuleElement;
import org.unidata.mdm.dq.core.type.model.instance.ValidatingRuleElement;
import org.unidata.mdm.dq.core.type.model.source.rule.EnrichmentSettings;
import org.unidata.mdm.dq.core.type.model.source.rule.QualityRuleSource;
import org.unidata.mdm.dq.core.type.model.source.rule.SelectionSettings;
import org.unidata.mdm.dq.core.type.model.source.rule.ValidationSettings;
import org.unidata.mdm.dq.core.type.rule.QualityRuleRunCondition;
import org.unidata.mdm.dq.core.type.rule.SeverityIndicator;

/**
 * @author Mikhail Mikhailov on Feb 28, 2021
 */
public class QualityRuleImpl
    extends AbstractNamedDisplayableCustomPropertiesImpl
    implements QualityRuleElement {
    /**
     * The source element.
     */
    private final QualityRuleSource source;
    /**
     * Validating part.
     */
    private final ValidatingRuleElement validating;
    /**
     * Enriching part.
     */
    private final EnrichingRuleElement enriching;
    /**
     * Cleanse function link.
     */
    private final CleanseFunctionElement cleanseFunction;
    /**
     * Constructor.
     * @param source
     */
    public QualityRuleImpl(DataQualityInstanceImpl dqi, QualityRuleSource source) {
        super(source.getName(), source.getDisplayName(), source.getDescription(), source.getCustomProperties());
        this.source = source;
        this.validating = Objects.nonNull(source.getValidationSettings()) ? new ValidatingRuleImpl(source.getValidationSettings()) : null;
        this.enriching = Objects.nonNull(source.getEnrichmentSettings()) ? new EnrichingRuleImpl(source.getEnrichmentSettings()) : null;
        this.cleanseFunction = dqi.getFunction(source.getCleanseFunctionName());
    }
    /**
     * Gets the source for internal MM use.
     * @return source
     */
    public QualityRuleSource getSource() {
        return source;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public String getId() {
        return getName();
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public OffsetDateTime getCreateDate() {
        return source.getCreateDate();
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public String getCreatedBy() {
        return source.getCreatedBy();
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public OffsetDateTime getUpdateDate() {
        return source.getUpdateDate();
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public String getUpdatedBy() {
        return source.getUpdatedBy();
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public CleanseFunctionElement getCleanseFunction() {
        return cleanseFunction;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public QualityRuleRunCondition getRunCondition() {
        return source.getRunCondition();
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean supports(String sourceSystem) {
        SelectionSettings ss = source.getSelectionSettings();
        return Objects.nonNull(ss) && (ss.isAll() || ss.getSourceSystems().contains(sourceSystem));
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isValidating() {
        return Objects.nonNull(validating);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public ValidatingRuleElement getValidating() {
        return validating;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isEnriching() {
        return Objects.nonNull(enriching);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public EnrichingRuleElement getEnriching() {
        return enriching;
    }
    /**
     * @author Mikhail Mikhailov on Feb 28, 2021
     * Enriching part implementation.
     */
    private static class EnrichingRuleImpl implements EnrichingRuleElement {

        private final EnrichmentSettings settings;
        /**
         * Constructor.
         * @param settings the settings
         */
        public EnrichingRuleImpl(EnrichmentSettings settings) {
            super();
            this.settings = settings;
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public String getSourceSystem() {
            return settings.getSourceSystem();
        }
    }
    /**
     * @author Mikhail Mikhailov on Feb 28, 2021
     * Validating part implementation.
     */
    private static class ValidatingRuleImpl implements ValidatingRuleElement {
        /**
         * The source settings.
         */
        private final ValidationSettings settings;
        /**
         * Constructor.
         * @param settings the settings
         */
        public ValidatingRuleImpl(ValidationSettings settings) {
            super();
            this.settings = settings;
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public String getRaisePort() {
            return settings.getRaisePort();
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public boolean hasMessagePort() {
            return StringUtils.isNotBlank(settings.getMessagePort());
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public String getMessagePort() {
            return settings.getMessagePort();
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public String getMessageText() {
            return settings.getMessageText();
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public boolean hasSeverityPort() {
            return StringUtils.isNotBlank(settings.getSeverityPort());
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public String getSeverityPort() {
            return settings.getSeverityPort();
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public SeverityIndicator getSeverityIndicator() {
            return settings.getSeverityIndicator();
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public int getSeverityScore() {
            return settings.getSeverityScore();
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public boolean hasCategoryPort() {
            return StringUtils.isNotBlank(settings.getCategoryPort());
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public String getCategoryPort() {
            return settings.getCategoryPort();
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public String getCategoryText() {
            return settings.getCategoryText();
        }
    }

}
